//！BlockChain base crate
//! This crate provides the basic data structure for a blockchain.
//! It only depends on the std library, bc_util crate and third party crates.

pub mod block;
pub mod constants;
pub mod misc_item;
pub mod script;
pub mod transaction;
pub mod wallet;

// #[cfg(test)]
pub mod test_utils;

mod opcode;
mod types;

// reexport opcode items
pub use opcode::{OpCode, Script};
pub use transaction::TransactionState;
pub use types::{
    BlockHeight, BlockId, Hash160Bytes, Hash256Bytes, TimeStamp, TransactionId, TransactionValue,
    blockchain_hash::BlockChainHash,
    private_key::PrivateKeyBytes,
    public_key::{PublicKeyBytes, PublicKeyHashBytes},
    signature::CompactSignatureBytes,
};

// use thiserror::Error;

#[derive(thiserror::Error, Debug, PartialEq)]
pub enum BlockChainBaseError {
    #[error("Public key bytes vector length is too short")]
    PubkeyBytesVecLenTooShort,

    #[error("Public key bytes hex string length is invalid")]
    PubkeyBytesHexStrLenInvalid,

    #[error("Public key hash bytes hex string length is invalid")]
    PubkeyHashBytesHexStrLenInvalid,

    #[error("Private key bytes hex string length is invalid")]
    PrivatekeyBytesHexStrLenInvalid,

    // hex::FromHexError
    #[error("Invalid hex string")]
    InvalidHexString(#[from] hex::FromHexError),

    #[error("Compact signature bytes vector length is too short")]
    CompactSigBytesVecLenTooShort,
}

#[cfg(test)]
mod tests_learning {
    #[test]
    fn test_key_pair_serialization() {
        let (bob_secret_key, bob_public_key) = bc_util::generate_secp256k1_keypair();
        let secret = bob_secret_key.secret_bytes();
        let pubkey = bob_public_key.serialize();

        assert_eq!(
            secret.len(),
            crate::constants::PRIVATE_KEY_BYTES_LENGTH,
            "Secret key should be {} bytes long, but it is {} bytes",
            crate::constants::PRIVATE_KEY_BYTES_LENGTH,
            secret.len()
        );
        assert_eq!(
            pubkey.len(),
            crate::constants::PUBLIC_KEY_BYTES_LENGTH,
            "Public key should be {} bytes long, but it is {} bytes",
            crate::constants::PUBLIC_KEY_BYTES_LENGTH,
            pubkey.len()
        );
    }
}
